<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        'use strict';
        // 使用严格模式
        // 1、函数内未经声明的变量不能使用
        // 2、直接声明在函数中this不指向window了
        
        
        // 声明函数的方法：
        // 函数声明  函数表达式(仅保留函数的名字)  构造函数
        function fn() {
            
        }
        var fn1 = function () {
            
        }
        var fn2 = new Function();

        // 函数的名字  function.name

        console.log(fn.name, fn1.name, fn2.name);

        /* 函数的形参
            形参个数 > 实参个数    多余的形参值是 undefined
            形参个数 < 实参个数    多余的实参存放在 arguments
            arguments 实参的集合，不定参函数
            关于简单类型与引用类型作为实参的区别：简单类型复制后与原值不粘连，引用类型值在函数内部发生更改，函数外边的值也会更改
            arguments.callee 对原函数的引用，在严格模式下不能使用
        */
        var obj = {};
        var a = 10;
        function add(v, n) {
            v.name = '李白';
            n += 20;
        }

        add(obj, a);
        console.log(obj);
        console.log(a); // 10

        // 求和  其一
        function sum() {
            var count = 0;
            for (var i = 0; i < arguments.length; i++) {
                count += arguments[i]
            }
            return count
        }
        // 求和  其二  
        function sum1(...args) {
            var count = 0;
            for (var i = 0; i < args.length; i++) {
                count += args[i]
            }
        }
        console.log(sum(1,2,3,4)); // 10

        // es6 剩余参数: 除却函数已知形参外，将传入剩余的实参保存成数组使用   函数形参使用 ...变量名   必须作为函数的最后一个形参
        
        // function.length    表示形参的个数，剩余参数不算形参的个数

        function sums(...args) {
            console.log('args', args);
        }
        function sums1(a, b, c, ...args) {
            console.log('args1', args);
        }
        function sums2(a, ...args) {
            console.log('args1', args);
        }

        sums(2,1,2,3,4,4);
        sums1(3,4,5,6,78,2)
        sums2(33,4,45,22,6,7,2);
 
        console.log('sums.length', sums.length); // 0
        console.log('sums1.length', sums1.length); // 3
        console.log('sums2.length', sums2.length); // 1

		// 递归函数   n! = n * (n-1)!
        function jc(n) {
            if (n === 1) {
                return 1;
            }
            return n*jc(n-1);
            // return n*arguments.callee(n-1); // 严格模式下无用
        }

        console.log(jc(4));

        function demo() {
            console.log(this);
        }
        demo()
        window.demo()
        var demo1 = function () {
            console.log(this);
        }
        demo1()
        window.demo1()
    </script>
</body>
</html>